package com.jbm.core.common;

import com.jbm.core.common.ResponseRecvCallback.KeepliveRRCallback;
import com.jbm.core.iface.IAcross;
import com.jbm.core.pb.PBIAcross;
import com.jbm.core.server.SAccount;

import javax.persistence.criteria.CriteriaBuilder;
import java.util.HashMap;

/**
 * Created by root on 17-3-5.
 */
public class AccountCtrl
{
	public static final Integer Account_Server_id = 0xFFFF0001;
	public static final AccountCtrl g_accountctrl = new AccountCtrl();

	protected Resource m_accountqueue;

	protected final Object m_accmap_mutex = new Object();
	protected HashMap<Integer,IAccount> m_accountmap;

	protected Resource m_caqueue;

	public AccountCtrl()
	{
	}

	public void InitAccountqueue(int rescnt)
	{
		m_accountqueue = new Resource(rescnt,"account");
	}

	public void InitAccountmap()
	{
		m_accountmap = new HashMap<Integer,IAccount>();
	}

	public void InitCAqueue(int rescnt)
	{
		m_caqueue = new Resource(rescnt,"connectagent");
	}

	public void AddCA(ConnectAgent ca)
	{
		m_caqueue.Add(ca);
	}

	public ConnectAgent GetorAddCA(String ca_key,ConnectAgent ca,boolean doadd)
	{
		return (ConnectAgent)m_caqueue.GetorAdd(null,null,doadd,ca,ca_key);
	}

	public ConnectAgent GetCA(Integer account_id,String app_type)
	{
		IAccount ia = null;

		synchronized (m_accmap_mutex)
		{
			ia = (IAccount) m_accountmap.get(account_id);
		}

		if ( ia == null )
			return null;

		return ia.GetCA(app_type);
	}

	public ConnectAgent[] GetCAS(Integer account_id)
	{
		IAccount ia = null;

		synchronized (m_accmap_mutex)
		{
			ia = (IAccount) m_accountmap.get(account_id);
		}

		if ( ia == null )
			return null;

		return ia.GetCAS();
	}

	public IAccount GetIA(Integer account_id)
	{
		IAccount ia = null;

		synchronized (m_accmap_mutex)
		{
			ia = (IAccount) m_accountmap.get(account_id);
		}

		return ia;
	}

	public SAccount GetSA(Integer account_id )
	{
		return (SAccount) m_accountqueue.Get(null,null,account_id);
	}

	public void AddSA(SAccount sa)
	{
		m_accountqueue.Add(sa);
	}

	public void NewSA(SAccount sa)
	{
	}

	public boolean Connect2Point( Integer account_id, String app_type )
	{
		ConnectAgent ca = GetCA(account_id,app_type);

		if ( ca == null )
			return false;

		return ca.ConnectP2P(true);
	}

	public boolean Connect2Server( Integer account_id, String app_type )
	{
		ConnectAgent ca = GetCA(account_id,app_type);

		if ( ca == null )
			return false;

		return ca.ConnectServer();
	}

	public ConnectAgent Connect2Local( Integer server_id, String app_type, int timeout )
	{
		ConnectAgent ca = new ConnectAgent(app_type,
				null,
				0,
				0,
				MainServer.Server_type_Server);

		ca.Born(0, timeout);
		ca.setM_keepalive(false);

		return AccountCtrl.g_accountctrl.GetorAddCA(null, ca, true);
	}

	public IAcross ServerSend(Integer to_id, String app_type, String classname, String method, IAcross content, boolean hasresp, boolean waitresp, boolean excode, boolean intask )
	{
		if ( classname == null )
			classname = content.getClass().getSimpleName();

//		content.m_timestamp = System.currentTimeMillis();

		PBIAcross.IAcross iacross = new PBRandR().BuildRequest(
				null,
				classname,
				method,
				MainServer.getG_server().getM_local_id(),
				to_id,
				MainServer.getG_server().getM_app_type(),
				app_type,
				0,
				excode,
				intask,
				content );

		iacross = iacross.toBuilder().setTimestamp(System.currentTimeMillis()).build();

		if ( !iacross.hasCode() )
			AutoCall.g_autocall.Call(iacross,MessageQueue.g_mq.m_rrcallback,true,to_id, app_type, MainServer.Server_type_Server);

		return null;
	}

	public IAcross SendPoint (ConnectAgent svr_ca, Integer to_id, String app_type, String classname, String method, IAcross content, boolean hasresp, boolean waitresp, boolean excode, boolean intask )
	{
		if ( svr_ca == null )
		{
			ConnectAgent ca = GetCA(to_id, app_type);

			if (ca == null)
				ca = GetCA(Account_Server_id, "app_server");

			return ca.Send(to_id, app_type, classname, method, content, hasresp, waitresp, excode, intask, ConnectAgent.Send_Type_Any, null,MainServer.Server_type_Client);
		}else
		{
			if ( classname == null )
				classname = content.getClass().getSimpleName();

			if ( to_id == null )
				to_id = Account_Server_id;

			int fromid = 0;

			if ( svr_ca.getM_iaccount() != null )
				fromid = svr_ca.getM_iaccount().getM_account_id();

			return AutoCall.g_autocall.Call(new IoSessionShell(null,svr_ca,MainServer.Server_type_Client),
					classname,method,
					content,
					fromid,to_id,
					svr_ca.getM_app_type(),app_type,svr_ca.GetQIndex(),
					hasresp,waitresp,excode,intask,null);
		}
	}

	public IAcross keepalive(Integer to_id, String app_type,boolean hasresp, boolean waitresp)
	{
		ConnectAgent ca = GetCA(to_id,app_type);

		if ( ca == null )
			ca = GetCA(Account_Server_id,"app_server");

		return ca.Send(to_id,app_type,"keepalive","",null,hasresp,waitresp,false,false,ConnectAgent.Send_Type_Any,new KeepliveRRCallback(ca,ca.getM_iosessionShell(MainServer.Server_type_Client)),MainServer.Server_type_Client);
	}

	public void PushPoint ( Integer account_id, ConnectAgent ca )
	{
		IAccount ia = null;

		synchronized (m_accmap_mutex)
		{
			ia = m_accountmap.get(account_id);
		}

		if ( ia == null )
		{
			ia = new IAccount(account_id);

			synchronized (m_accmap_mutex)
			{
				m_accountmap.put(account_id, ia);
			}
		}
/*
		else if ( ia.... != account.... )
			//call callback;
*/
		ia.Push2Map(ca,MainServer.getG_server().getM_maincallback());

	}

	public void OfflinePoint ( Integer account_id, ConnectAgent ca )
	{
		IAccount ia = null;

		synchronized (m_accmap_mutex)
		{
			ia = m_accountmap.get(account_id);
		}

		if ( ia != null )
		{
			ia.Offline2Map(ca,MainServer.getG_server().getM_maincallback());
		}
	}
}
